import json
import os
from enum import Enum
import constants as const
from tools import tools
from resource_path import resource_path  # 导入资源路径处理函数

class MapType(Enum):
    NORMAL = 1
    CUSTOM = 2

class CardData:
    def __init__(self, uid, layerid, index, cardid= 0, x=0, y=0, rotation=0):
        self.uid = uid
        self.layerid = layerid
        self.index = index
        self.x = x
        self.y = y
        self.firstopen = False
        self.cardid = cardid        # 正常值【A == 0, 2 = 1  5】 牌背【55】 自定义牌【56+】
        self.cardpoolid = '0'    # 牌库 id
        self.ruleid = '0'        # 规则库 id
        self.iscustom = False
        self.rotation = rotation   # 卡牌的旋转角度，默认为0度
    
    @staticmethod
    def from_dict(card_data):
        # 创建一个新的CardData实例
        uid = card_data.get('uid', '0')
        layerid = card_data.get('layerid', '0')
        index = card_data.get('index', '0')
        cardid = card_data.get('cardid', '0')
        rotation = card_data.get('rotation', 0)
        
        # 处理坐标转换
        x = card_data.get('x', 0)
        y = card_data.get('y', 0)

        x, y = tools.convert_to_left(x, y)
        
        # 创建实例
        card = CardData(uid, layerid, index, cardid, x, y, rotation)
        
        # 设置其他属性
        card.firstopen = card_data.get('firstopen', False)
        card.cardpoolid = str(card_data.get('cardpoolid', '0'))
        card.ruleid = str(card_data.get('ruleid', '0'))
        card.iscustom = card_data.get('iscustom', False)
        
        return card
        
    def to_dict(self):
        x, y = tools.convert_to_centered(self.x, self.y)
        return {
            'uid': self.uid,
            'layerid': self.layerid,
            'index': self.index,
            'x': x,
            'y': y,
            'firstopen': self.firstopen,
            'cardid': self.cardid,
            'cardpoolid': self.cardpoolid,
            'ruleid': self.ruleid,
            'iscustom': self.iscustom,
            'rotation': self.rotation
        }
    
    #
    def suit(self, isstr = False):
        if self.iscustom:
            return f"{self.ruleid}"
        
        suit =  const.CARD_BACKGROUND if self.cardid < 0 else self.cardid // const.ranks_count
        if isstr:
            return const.suits_str[suit] if suit >=0 and self.cardid < const.CARD_CUSTOM_RULE else '*'
        else:
            return suit

    def rank(self, isstr = False):
        if self.iscustom:
            return f"{self.cardpoolid}"
        
        rank =  const.CARD_BACKGROUND if self.cardid < 0 else self.cardid % const.ranks_count
        if isstr:
            return const.ranks_str[rank] if rank >= 0 and rank < const.CARD_CUSTOM_RULE else '*'
        else:
            return rank
    
    def card_str(self, suitPrefix = False):
        if self.iscustom:
            return f"*{self.cardpoolid}"
        
        suit = self.suit(True)
        rank = self.rank(True)

        if suitPrefix:
            return f"{suit}{rank}"
        else:
            return f"{rank}{suit}"

    def to_id(self, suit, rank):
        suitIndex = const.suits_str.index(suit)
        rankIndex = const.ranks_str.index(rank)
        return suitIndex * const.ranks_count + rankIndex

class MapData:
    def __init__(self):
        self.width = 0
        self.height = 0
        self.lv = 0
        self.type = MapType.NORMAL
        self.uid = ''
        self.ver = 0
        self.curver = 0 # 当前版本
        self.cards = {}  # 字典结构 {CardData.uid: CardData}
        self.cuids = []  # 二维数组结构 [[uid, uid, ...], [uid, uid, ...]]

        self.startuid = 0

    def isLoad(self):
        return self.uid != ''

    def set_data(self, uid, width, height, mtype = MapType.NORMAL):
        self.lv = int(uid) % 100000
        self.width = width
        self.height = height
        self.uid = uid
        self.type = mtype

        self.cards = {}
        self.cuids = []
        self.startuid = 0
        self.make_ver_change()

    def to_dict(self):
        # 保留cards的字典结构，将每个CardData对象转换为字典
        cards_dict = {}
        for uid, card in self.cards.items():
            cards_dict[uid] = card.to_dict()
        
        return {
            'uid': self.uid,
            'lv': self.lv,
            'width': self.width,
            'height': self.height,
            'ver': self.ver,
            'cards': cards_dict,
            'cuids': self.cuids,
            'startuid': self.startuid
        }

    def is_change(self):
        return self.ver != self.curver
    def make_ver_change(self):
        self.curver += 1
    
    def set_card(self, card):
        layerid = card.layerid

        l = self.cuids[layerid]

        if len(l) <= card.index:
            # 将卡牌添加到cards字典中
            self.cuids[layerid].append(card.uid)
        else:
            self.cuids[layerid][card.index] = card.uid

        self.cards[card.uid] = card
        self.make_ver_change()
    def get_card(self, layerid, index):
        if layerid < len(self.cuids) and index < len(self.cuids[layerid]):
            uid = self.cuids[layerid][index]
            if uid in self.cards:
                return self.cards[uid]
        return None
    def get_layer_all_cards(self, layerid):
        if layerid < len(self.cuids):
            # 返回该层所有卡牌的列表
            return [self.cards[uid] for uid in self.cuids[layerid] if uid in self.cards]
    
    def get_layer_all_uid(self, layerid):
        if layerid < len(self.cuids):
            # 返回该层所有卡牌的uid列表
            return [uid for uid in self.cuids[layerid] if uid is not None]
        return []
    
    def get_all_cards(self):
        # 返回所有卡牌对象的列表
        return list(self.cards.values())

    def new_layer(self, layerid = const.NONE_INT):
        if layerid == const.NONE_INT:
            layerid = len(self.cuids)
            self.cuids.append([])
            self.make_ver_change()
            return layerid
        return const.NONE_INT

    def del_layer(self, layerid = const.NONE_INT):
        index = layerid if layerid != const.NONE_INT else len(self.cuids) - 1
        if index >= 0:
            ls = self.cuids[index]
            del self.cuids[index]
            return ls
        return []
    
    def new_card(self, uid, layerid, index, x=0, y=0, cardId = 0, rotation=0):
        data  = CardData(uid, layerid, index, cardId, x, y, rotation)
        self.set_card(data)
        return data
    
    def del_card(self, uid):
        cd = self.cards.get(uid)
        if cd and cd.uid == uid:
            self.cuids[cd.layerid].remove(uid)
            self.cards.pop(uid)
            return True
        return False

    def save_to_file(self, filepath = None):
        if filepath != self.uid:
            self.uid = filepath
            self.make_ver_change()

        fillpath = self.get_full_path(filepath)
        if self.is_change():
            with open(fillpath, 'w', encoding='utf-8') as f:
                json.dump(self.to_dict(), f, ensure_ascii=False, indent=4)
            return True
        return False
    
    def get_full_path(self, name = None):
        if not name:
            name = self.uid 
        # 使用resource_path函数获取maps目录的路径
        # 无论是否在打包环境中，都使用exe同级目录下的res/maps文件夹
        maps_dir = os.path.join(resource_path('res'), 'maps')
        # 确保目录存在
        if not os.path.exists(maps_dir):
            os.makedirs(maps_dir, exist_ok=True)
        
        return os.path.join(maps_dir, f"{name}.json")
    def load_from_file(self, filepath = None):
        if filepath is None:
            filepath = self.uid
            
        # 检查filepath是否已经包含.json后缀
        if not filepath.endswith('.json'):
            filename = f"{filepath}.json"
        else:
            filename = filepath
            
        # 无论是否在打包环境中，都使用exe同级目录下的res/maps文件夹
        maps_dir = os.path.join(resource_path('res'), 'maps')
        full_path = os.path.join(maps_dir, filename)
        
        # 确保目录存在
        if not os.path.exists(maps_dir):
            os.makedirs(maps_dir, exist_ok=True)
        with open(full_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
            self.uid = data['uid']
            self.lv = data['lv']
            self.width = data.get('width', 0)
            self.height = data.get('height', 0)
            self.ver = data.get('ver', 0)
            self.curver = self.ver
            self.startuid = data.get('startuid', 0)
            
            # 重置cards和cuids
            self.cards = {}
            self.cuids = []
            
            # 加载cards数据
            if 'cards' in data:
                # 检查cards是字典结构还是旧的二维数组结构
                if isinstance(data['cards'], dict):
                    # 新的字典结构
                    for uid, card_data in data['cards'].items():
                        nuid = int(uid)
                        # 使用CardData的from_dict静态方法创建卡牌实例
                        card = CardData.from_dict(card_data)
                        
                        # 将卡牌添加到cards字典
                        self.cards[nuid] = card
            
            # 如果JSON中包含cuids数据，则直接使用
            if 'cuids' in data:
                self.cuids = data['cuids']

    def adjust_layer_index(self, uid, layerid, flag = 1):
        newlayerid = layerid + flag
        if newlayerid < len(self.cuids):
            self.cuids[newlayerid].append(uid)
            self.cuids[layerid].remove(uid)

            cd = self.cards.get(uid)
            if cd:
                cd.layerid = newlayerid
                cd.index = len(self.cuids[newlayerid]) -1
                return True
        
        return False

    def get_card_uid(self):
        self.startuid += 1
        return self.startuid

    def get_draw_list(self):
        pls = []
        for layerid, uids in enumerate(self.cuids):
            for index, uid in enumerate(uids):
                card = self.cards.get(uid)
                if card:
                    card.layerid = layerid
                    card.index = index
                    pls.append(uid)
        return pls